<?php

// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// OneThink常量定义
const ONETHINK_VERSION = '1.1.141101';
const ONETHINK_ADDON_PATH = './Addons/';

/**
 * 系统公共库文件
 * 主要定义系统公共函数库
 */

/**
 * 检测用户是否登录
 * @return integer 0-未登录，大于0-当前登录用户ID
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_login() {
    $user = session('user_auth');
    if (empty($user)) {
        return 0;
    } else {
        return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
    }
}

/**
 * 检测当前用户是否为管理员
 * @return boolean true-管理员，false-非管理员
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_administrator($uid = null) {
    $uid = is_null($uid) ? is_login() : $uid;
    return $uid && (intval($uid) === C('USER_ADMINISTRATOR'));
}

/**
 * 字符串转换为数组，主要用于把分隔符调整到第二个参数
 * @param  string $str  要分割的字符串
 * @param  string $glue 分割符
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function str2arr($str, $glue = ',') {
    return explode($glue, $str);
}

/**
 * 数组转换为字符串，主要用于把分隔符调整到第二个参数
 * @param  array  $arr  要连接的数组
 * @param  string $glue 分割符
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function arr2str($arr, $glue = ',') {
    return implode($glue, $arr);
}

/**
 * 字符串截取，支持中文和其他编码
 * @static
 * @access public
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 * @return string
 */
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) {
    if (function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif (function_exists('iconv_substr')) {
        $slice = iconv_substr($str, $start, $length, $charset);
        if (false === $slice) {
            $slice = '';
        }
    } else {
        $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("", array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice . '...' : $slice;
}

/**
 * 系统加密方法
 * @param string $data 要加密的字符串
 * @param string $key  加密密钥
 * @param int $expire  过期时间 单位 秒
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_encrypt($data, $key = '', $expire = 0) {
    $key = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = base64_encode($data);
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l)
            $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    $str = sprintf('%010d', $expire ? $expire + time() : 0);

    for ($i = 0; $i < $len; $i++) {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
    }
    return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($str));
}

/**
 * 系统解密方法
 * @param  string $data 要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param  string $key  加密密钥
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_decrypt($data, $key = '') {
    $key = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = str_replace(array('-', '_'), array('+', '/'), $data);
    $mod4 = strlen($data) % 4;
    if ($mod4) {
        $data .= substr('====', $mod4);
    }
    $data = base64_decode($data);
    $expire = substr($data, 0, 10);
    $data = substr($data, 10);

    if ($expire > 0 && $expire < time()) {
        return '';
    }
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = $str = '';

    for ($i = 0; $i < $len; $i++) {
        if ($x == $l)
            $x = 0;
        $char .= substr($key, $x, 1);
        $x++;
    }

    for ($i = 0; $i < $len; $i++) {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        } else {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return base64_decode($str);
}

/**
 * 数据签名认证
 * @param  array  $data 被认证的数据
 * @return string       签名
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function data_auth_sign($data) {
    //数据类型检测
    if (!is_array($data)) {
        $data = (array) $data;
    }
    ksort($data); //排序
    $code = http_build_query($data); //url编码并生成query字符串
    $sign = sha1($code); //生成签名
    return $sign;
}

/**
 * 对查询结果集进行排序
 * @access public
 * @param array $list 查询结果
 * @param string $field 排序的字段名
 * @param array $sortby 排序类型
 * asc正向排序 desc逆向排序 nat自然排序
 * @return array
 */
function list_sort_by($list, $field, $sortby = 'asc') {
    if (is_array($list)) {
        $refer = $resultSet = array();
        foreach ($list as $i => $data)
            $refer[$i] = &$data[$field];
        switch ($sortby) {
            case 'asc': // 正向排序
                asort($refer);
                break;
            case 'desc':// 逆向排序
                arsort($refer);
                break;
            case 'nat': // 自然排序
                natcasesort($refer);
                break;
        }
        foreach ($refer as $key => $val)
            $resultSet[] = &$list[$key];
        return $resultSet;
    }
    return false;
}

/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
    // 创建Tree
    $tree = array();
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] = & $list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[] = & $list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = & $refer[$parentId];
                    $parent[$child][] = & $list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * 将list_to_tree的树还原成列表
 * @param  array $tree  原来的树
 * @param  string $child 孩子节点的键
 * @param  string $order 排序显示的键，一般是主键 升序排列
 * @param  array  $list  过渡用的中间数组，
 * @return array        返回排过序的列表数组
 * @author yangweijie <yangweijiester@gmail.com>
 */
function tree_to_list($tree, $child = '_child', $order = 'id', &$list = array()) {
    if (is_array($tree)) {
        foreach ($tree as $key => $value) {
            $reffer = $value;
            if (isset($reffer[$child])) {
                unset($reffer[$child]);
                tree_to_list($value[$child], $child, $order, $list);
            }
            $list[] = $reffer;
        }
        $list = list_sort_by($list, $order, $sortby = 'asc');
    }
    return $list;
}

/**
 * 格式化字节大小
 * @param  number $size      字节数
 * @param  string $delimiter 数字和单位分隔符
 * @return string            格式化后的带单位的大小
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function format_bytes($size, $delimiter = '') {
    $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
    for ($i = 0; $size >= 1024 && $i < 5; $i++)
        $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 设置跳转页面URL
 * 使用函数再次封装，方便以后选择不同的存储方式（目前使用cookie存储）
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function set_redirect_url($url) {
    cookie('redirect_url', $url);
}

/**
 * 获取跳转页面URL
 * @return string 跳转页URL
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function get_redirect_url() {
    $url = cookie('redirect_url');
    return empty($url) ? __APP__ : $url;
}

/**
 * 处理插件钩子
 * @param string $hook   钩子名称
 * @param mixed $params 传入参数
 * @return void
 */
function hook($hook, $params = array()) {
    \Think\Hook::listen($hook, $params);
}

/**
 * 获取插件类的类名
 * @param strng $name 插件名
 */
function get_addon_class($name) {
    $class = "Addons\\{$name}\\{$name}Addon";
    return $class;
}

/**
 * 获取插件类的配置文件数组
 * @param string $name 插件名
 */
function get_addon_config($name) {
    $class = get_addon_class($name);
    if (class_exists($class)) {
        $addon = new $class();
        return $addon->getConfig();
    } else {
        return array();
    }
}

/**
 * 插件显示内容里生成访问插件的url
 * @param string $url url
 * @param array $param 参数
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function addons_url($url, $param = array()) {
    $url = parse_url($url);
    $case = C('URL_CASE_INSENSITIVE');
    $addons = $case ? parse_name($url['scheme']) : $url['scheme'];
    $controller = $case ? parse_name($url['host']) : $url['host'];
    $action = trim($case ? strtolower($url['path']) : $url['path'], '/');

    /* 解析URL带的参数 */
    if (isset($url['query'])) {
        parse_str($url['query'], $query);
        $param = array_merge($query, $param);
    }

    /* 基础参数 */
    $params = array(
        '_addons' => $addons,
        '_controller' => $controller,
        '_action' => $action,
    );
    $params = array_merge($params, $param); //添加额外参数

    return U('Addons/execute', $params);
}

/**
 * 时间戳格式化
 * @param int $time
 * @return string 完整的时间显示
 * @author huajie <banhuajie@163.com>
 */
function time_format($time = NULL, $format = 'Y-m-d H:i') {
    $time = $time === NULL ? NOW_TIME : intval($time);
    return date($format, $time);
}

/**
 * 根据用户ID获取用户名
 * @param  integer $uid 用户ID
 * @return string       用户名
 */
function get_username($uid = 0) {
    static $list;
    if (!($uid && is_numeric($uid))) { //获取当前登录用户名
        return session('user_auth.username');
    }

    /* 获取缓存数据 */
    if (empty($list)) {
        $list = S('sys_active_user_list');
    }

    /* 查找用户信息 */
    $key = "u{$uid}";
    if (isset($list[$key])) { //已缓存，直接使用
        $name = $list[$key];
    } else { //调用接口获取用户信息
        $User = new User\Api\UserApi();
        $info = $User->info($uid);
        if ($info && isset($info[1])) {
            $name = $list[$key] = $info[1];
            /* 缓存用户 */
            $count = count($list);
            $max = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            S('sys_active_user_list', $list);
        } else {
            $name = '';
        }
    }
    return $name;
}

/**
 * 根据用户ID获取用户昵称
 * @param  integer $uid 用户ID
 * @return string       用户昵称
 */
function get_nickname($uid = 0) {
    static $list;
    if (!($uid && is_numeric($uid))) { //获取当前登录用户名
        return session('user_auth.username');
    }

    /* 获取缓存数据 */
    if (empty($list)) {
        $list = S('sys_user_nickname_list');
    }

    /* 查找用户信息 */
    $key = "u{$uid}";
    if (isset($list[$key])) { //已缓存，直接使用
        $name = $list[$key];
    } else { //调用接口获取用户信息
        $info = M('Member')->field('nickname')->find($uid);
        if ($info !== false && $info['nickname']) {
            $nickname = $info['nickname'];
            $name = $list[$key] = $nickname;
            /* 缓存用户 */
            $count = count($list);
            $max = C('USER_MAX_CACHE');
            while ($count-- > $max) {
                array_shift($list);
            }
            S('sys_user_nickname_list', $list);
        } else {
            $name = '';
        }
    }
    return $name;
}

/**
 * 获取分类信息并缓存分类
 * @param  integer $id    分类ID
 * @param  string  $field 要获取的字段名
 * @return string         分类信息
 */
function get_category($id, $field = null) {
    static $list;

    /* 非法分类ID */
    if (empty($id) || !is_numeric($id)) {
        return '';
    }

    /* 读取缓存数据 */
    if (empty($list)) {
        $list = S('sys_category_list');
    }

    /* 获取分类名称 */
    if (!isset($list[$id])) {
        $cate = M('Category')->find($id);
        if (!$cate || 1 != $cate['status']) { //不存在分类，或分类被禁用
            return '';
        }
        $list[$id] = $cate;
        S('sys_category_list', $list); //更新缓存
    }
    return is_null($field) ? $list[$id] : $list[$id][$field];
}

/* 根据ID获取分类标识 */

function get_category_name($id) {
    return get_category($id, 'name');
}

/* 根据ID获取分类名称 */

function get_category_title($id) {
    return get_category($id, 'title');
}

/**
 * 获取顶级模型信息
 */
function get_top_model($model_id = null) {
    $map = array('status' => 1, 'extend' => 0);
    if (!is_null($model_id)) {
        $map['id'] = array('neq', $model_id);
    }
    $model = M('Model')->where($map)->field(true)->select();
    foreach ($model as $value) {
        $list[$value['id']] = $value;
    }
    return $list;
}

/**
 * 获取文档模型信息
 * @param  integer $id    模型ID
 * @param  string  $field 模型字段
 * @return array
 */
function get_document_model($id = null, $field = null) {
    static $list;

    /* 非法分类ID */
    if (!(is_numeric($id) || is_null($id))) {
        return '';
    }

    /* 读取缓存数据 */
    if (empty($list)) {
        $list = S('DOCUMENT_MODEL_LIST');
    }

    /* 获取模型名称 */
    if (empty($list)) {
        $map = array('status' => 1, 'extend' => 1);
        $model = M('Model')->where($map)->field(true)->select();
        foreach ($model as $value) {
            $list[$value['id']] = $value;
        }
        S('DOCUMENT_MODEL_LIST', $list); //更新缓存
    }

    /* 根据条件返回数据 */
    if (is_null($id)) {
        return $list;
    } elseif (is_null($field)) {
        return $list[$id];
    } else {
        return $list[$id][$field];
    }
}

/**
 * 解析UBB数据
 * @param string $data UBB字符串
 * @return string 解析为HTML的数据
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function ubb($data) {
    //TODO: 待完善，目前返回原始数据
    return $data;
}

/**
 * 记录行为日志，并执行该行为的规则
 * @param string $action 行为标识
 * @param string $model 触发行为的模型名
 * @param int $record_id 触发行为的记录id
 * @param int $user_id 执行行为的用户id
 * @return boolean
 * @author huajie <banhuajie@163.com>
 */
function action_log($action = null, $model = null, $record_id = null, $user_id = null) {

    //参数检查
    if (empty($action) || empty($model) || empty($record_id)) {
        return '参数不能为空';
    }
    if (empty($user_id)) {
        $user_id = is_login();
    }

    //查询行为,判断是否执行
    $action_info = M('Action')->getByName($action);
    if ($action_info['status'] != 1) {
        return '该行为被禁用或删除';
    }

    //插入行为日志
    $data['action_id'] = $action_info['id'];
    $data['user_id'] = $user_id;
    $data['action_ip'] = ip2long(get_client_ip());
    $data['model'] = $model;
    $data['record_id'] = $record_id;
    $data['create_time'] = NOW_TIME;

    //解析日志规则,生成日志备注
    if (!empty($action_info['log'])) {
        if (preg_match_all('/\[(\S+?)\]/', $action_info['log'], $match)) {
            $log['user'] = $user_id;
            $log['record'] = $record_id;
            $log['model'] = $model;
            $log['time'] = NOW_TIME;
            $log['data'] = array('user' => $user_id, 'model' => $model, 'record' => $record_id, 'time' => NOW_TIME);
            foreach ($match[1] as $value) {
                $param = explode('|', $value);
                if (isset($param[1])) {
                    $replace[] = call_user_func($param[1], $log[$param[0]]);
                } else {
                    $replace[] = $log[$param[0]];
                }
            }
            $data['remark'] = str_replace($match[0], $replace, $action_info['log']);
        } else {
            $data['remark'] = $action_info['log'];
        }
    } else {
        //未定义日志规则，记录操作url
        $data['remark'] = '操作url：' . $_SERVER['REQUEST_URI'];
    }

    M('ActionLog')->add($data);

    if (!empty($action_info['rule'])) {
        //解析行为
        $rules = parse_action($action, $user_id);

        //执行行为
        $res = execute_action($rules, $action_info['id'], $user_id);
    }
}

/**
 * 解析行为规则
 * 规则定义  table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
 * 规则字段解释：table->要操作的数据表，不需要加表前缀；
 *              field->要操作的字段；
 *              condition->操作的条件，目前支持字符串，默认变量{$self}为执行行为的用户
 *              rule->对字段进行的具体操作，目前支持四则混合运算，如：1+score*2/2-3
 *              cycle->执行周期，单位（小时），表示$cycle小时内最多执行$max次
 *              max->单个周期内的最大执行次数（$cycle和$max必须同时定义，否则无效）
 * 单个行为后可加 ； 连接其他规则
 * @param string $action 行为id或者name
 * @param int $self 替换规则里的变量为执行用户的id
 * @return boolean|array: false解析出错 ， 成功返回规则数组
 * @author huajie <banhuajie@163.com>
 */
function parse_action($action = null, $self) {
    if (empty($action)) {
        return false;
    }

    //参数支持id或者name
    if (is_numeric($action)) {
        $map = array('id' => $action);
    } else {
        $map = array('name' => $action);
    }

    //查询行为信息
    $info = M('Action')->where($map)->find();
    if (!$info || $info['status'] != 1) {
        return false;
    }

    //解析规则:table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
    $rules = $info['rule'];
    $rules = str_replace('{$self}', $self, $rules);
    $rules = explode(';', $rules);
    $return = array();
    foreach ($rules as $key => &$rule) {
        $rule = explode('|', $rule);
        foreach ($rule as $k => $fields) {
            $field = empty($fields) ? array() : explode(':', $fields);
            if (!empty($field)) {
                $return[$key][$field[0]] = $field[1];
            }
        }
        //cycle(检查周期)和max(周期内最大执行次数)必须同时存在，否则去掉这两个条件
        if (!array_key_exists('cycle', $return[$key]) || !array_key_exists('max', $return[$key])) {
            unset($return[$key]['cycle'], $return[$key]['max']);
        }
    }

    return $return;
}

/**
 * 执行行为
 * @param array $rules 解析后的规则数组
 * @param int $action_id 行为id
 * @param array $user_id 执行的用户id
 * @return boolean false 失败 ， true 成功
 * @author huajie <banhuajie@163.com>
 */
function execute_action($rules = false, $action_id = null, $user_id = null) {
    if (!$rules || empty($action_id) || empty($user_id)) {
        return false;
    }

    $return = true;
    foreach ($rules as $rule) {

        //检查执行周期
        $map = array('action_id' => $action_id, 'user_id' => $user_id);
        $map['create_time'] = array('gt', NOW_TIME - intval($rule['cycle']) * 3600);
        $exec_count = M('ActionLog')->where($map)->count();
        if ($exec_count > $rule['max']) {
            continue;
        }

        //执行数据库操作
        $Model = M(ucfirst($rule['table']));
        $field = $rule['field'];
        $res = $Model->where($rule['condition'])->setField($field, array('exp', $rule['rule']));

        if (!$res) {
            $return = false;
        }
    }
    return $return;
}

//基于数组创建目录和文件
function create_dir_or_files($files) {
    foreach ($files as $key => $value) {
        if (substr($value, -1) == '/') {
            mkdir($value);
        } else {
            @file_put_contents($value, '');
        }
    }
}

if (!function_exists('array_column')) {

    function array_column(array $input, $columnKey, $indexKey = null) {
        $result = array();
        if (null === $indexKey) {
            if (null === $columnKey) {
                $result = array_values($input);
            } else {
                foreach ($input as $row) {
                    $result[] = $row[$columnKey];
                }
            }
        } else {
            if (null === $columnKey) {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row;
                }
            } else {
                foreach ($input as $row) {
                    $result[$row[$indexKey]] = $row[$columnKey];
                }
            }
        }
        return $result;
    }

}

/**
 * 获取表名（不含表前缀）
 * @param string $model_id
 * @return string 表名
 * @author huajie <banhuajie@163.com>
 */
function get_table_name($model_id = null) {
    if (empty($model_id)) {
        return false;
    }
    $Model = M('Model');
    $name = '';
    $info = $Model->getById($model_id);
    if ($info['extend'] != 0) {
        $name = $Model->getFieldById($info['extend'], 'name') . '_';
    }
    $name .= $info['name'];
    return $name;
}

/**
 * 获取属性信息并缓存
 * @param  integer $id    属性ID
 * @param  string  $field 要获取的字段名
 * @return string         属性信息
 */
function get_model_attribute($model_id, $group = true, $fields = true) {
    static $list;

    /* 非法ID */
    if (empty($model_id) || !is_numeric($model_id)) {
        return '';
    }

    /* 获取属性 */
    if (!isset($list[$model_id])) {
        $map = array('model_id' => $model_id);
        $extend = M('Model')->getFieldById($model_id, 'extend');

        if ($extend) {
            $map = array('model_id' => array("in", array($model_id, $extend)));
        }
        $info = M('Attribute')->where($map)->field($fields)->select();
        $list[$model_id] = $info;
    }

    $attr = array();
    if ($group) {
        foreach ($list[$model_id] as $value) {
            $attr[$value['id']] = $value;
        }
        $model = M("Model")->field("field_sort,attribute_list,attribute_alias")->find($model_id);
        $attribute = explode(",", $model['attribute_list']);
        if (empty($model['field_sort'])) { //未排序
            $group = array(1 => array_merge($attr));
        } else {
            $group = json_decode($model['field_sort'], true);

            $keys = array_keys($group);
            foreach ($group as &$value) {
                foreach ($value as $key => $val) {
                    $value[$key] = $attr[$val];
                    unset($attr[$val]);
                }
            }

            if (!empty($attr)) {
                foreach ($attr as $key => $val) {
                    if (!in_array($val['id'], $attribute)) {
                        unset($attr[$key]);
                    }
                }
                $group[$keys[0]] = array_merge($group[$keys[0]], $attr);
            }
        }
        if (!empty($model['attribute_alias'])) {
            $alias = preg_split('/[;\r\n]+/s', $model['attribute_alias']);
            $fields = array();
            foreach ($alias as &$value) {
                $val = explode(':', $value);
                $fields[$val[0]] = $val[1];
            }
            foreach ($group as &$value) {
                foreach ($value as $key => $val) {
                    if (!empty($fields[$val['name']])) {
                        $value[$key]['title'] = $fields[$val['name']];
                    }
                }
            }
        }
        $attr = $group;
    } else {
        foreach ($list[$model_id] as $value) {
            $attr[$value['name']] = $value;
        }
    }
    return $attr;
}

/**
 * 调用系统的API接口方法（静态方法）
 * api('User/getName','id=5'); 调用公共模块的User接口的getName方法
 * api('Admin/User/getName','id=5');  调用Admin模块的User接口
 * @param  string  $name 格式 [模块名]/接口名/方法名
 * @param  array|string  $vars 参数
 */
function api($name, $vars = array()) {
    $array = explode('/', $name);
    $method = array_pop($array);
    $classname = array_pop($array);
    $module = $array ? array_pop($array) : 'Common';
    $callback = $module . '\\Api\\' . $classname . 'Api::' . $method;
    if (is_string($vars)) {
        parse_str($vars, $vars);
    }
    return call_user_func_array($callback, $vars);
}

/**
 * 根据条件字段获取指定表的数据
 * @param mixed $value 条件，可用常量或者数组
 * @param string $condition 条件字段
 * @param string $field 需要返回的字段，不传则返回整个数据
 * @param string $table 需要查询的表
 * @author huajie <banhuajie@163.com>
 */
function get_table_field($value = null, $condition = 'id', $field = null, $table = null) {
    if (empty($value) || empty($table)) {
        return false;
    }

    //拼接参数
    $map[$condition] = $value;
    $info = M(ucfirst($table))->where($map);
    if (empty($field)) {
        $info = $info->field(true)->find();
    } else {
        $info = $info->getField($field);
    }
    return $info;
}

/**
 * 获取链接信息
 * @param int $link_id
 * @param string $field
 * @return 完整的链接信息或者某一字段
 * @author huajie <banhuajie@163.com>
 */
function get_link($link_id = null, $field = 'url') {
    $link = '';
    if (empty($link_id)) {
        return $link;
    }
    $link = M('Url')->getById($link_id);
    if (empty($field)) {
        return $link;
    } else {
        return $link[$field];
    }
}

/**
 * 获取文档封面图片
 * @param int $cover_id
 * @param string $field
 * @return 完整的数据  或者  指定的$field字段值
 * @author huajie <banhuajie@163.com>
 */
function get_cover($cover_id, $field = null) {
    if (empty($cover_id)) {
        return false;
    }
    $picture = M('Picture')->where(array('status' => 1))->getById($cover_id);
    if ($field == 'path') {
        if (!empty($picture['url'])) {
            $picture['path'] = $picture['url'];
        } else {
            $picture['path'] = __ROOT__ . $picture['path'];
        }
    }
    return empty($field) ? $picture : $picture[$field];
}

/**
 * 检查$pos(推荐位的值)是否包含指定推荐位$contain
 * @param number $pos 推荐位的值
 * @param number $contain 指定推荐位
 * @return boolean true 包含 ， false 不包含
 * @author huajie <banhuajie@163.com>
 */
function check_document_position($pos = 0, $contain = 0) {
    if (empty($pos) || empty($contain)) {
        return false;
    }

    //将两个参数进行按位与运算，不为0则表示$contain属于$pos
    $res = $pos & $contain;
    if ($res !== 0) {
        return true;
    } else {
        return false;
    }
}

/**
 * 获取数据的所有子孙数据的id值
 * @author 朱亚杰 <xcoolcc@gmail.com>
 */
function get_stemma($pids, Model &$model, $field = 'id') {
    $collection = array();

    //非空判断
    if (empty($pids)) {
        return $collection;
    }

    if (is_array($pids)) {
        $pids = trim(implode(',', $pids), ',');
    }
    $result = $model->field($field)->where(array('pid' => array('IN', (string) $pids)))->select();
    $child_ids = array_column((array) $result, 'id');

    while (!empty($child_ids)) {
        $collection = array_merge($collection, $result);
        $result = $model->field($field)->where(array('pid' => array('IN', $child_ids)))->select();
        $child_ids = array_column((array) $result, 'id');
    }
    return $collection;
}

/**
 * 验证分类是否允许发布内容
 * @param  integer $id 分类ID
 * @return boolean     true-允许发布内容，false-不允许发布内容
 */
function check_category($id) {
    if (is_array($id)) {
        $id['type'] = !empty($id['type']) ? $id['type'] : 2;
        $type = get_category($id['category_id'], 'type');
        $type = explode(",", $type);
        return in_array($id['type'], $type);
    } else {
        $publish = get_category($id, 'allow_publish');
        return $publish ? true : false;
    }
}

/**
 * 检测分类是否绑定了指定模型
 * @param  array $info 模型ID和分类ID数组
 * @return boolean     true-绑定了模型，false-未绑定模型
 */
function check_category_model($info) {
    $cate = get_category($info['category_id']);
    $array = explode(',', $info['pid'] ? $cate['model_sub'] : $cate['model']);
    return in_array($info['model_id'], $array);
}

/**
 * 获取接口信息
 * @param string $apiCode
 * @author 刘新
 */
function api_info($apiCode) {
//	$api = S(C('API_CACHE_NAME'), '');
//	//测试代码
//	return $api[$apiCode];
    //调试模式直接从库中查询
    if (APP_DEBUG) {
        $api = M('Api')->field('id,code,name,module,controller,action,status,method')->where(array('status' => 1, 'code' => $apiCode))->find();
        return $api;
        //部署模式从缓存中获取
    } else {
        if ($api)
            return $api[$apiCode];
        return false;
    }
}

/**
 * 组装加密字符串
 * @param array $param
 * @param string $first
 * @return string
 */
function concat(array $param) {
    $para_filter = paraFilter($param);
    ksort($para_filter);
    $first = '';
    foreach ($para_filter as $key => $val) {
        if (is_array($val)) {
            $first .= concat($val);
            continue;
        }

        if (!empty($val)) {
            $first .= $val;
        }
    }
    return $first;
}

/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function paraFilter($para) {
    $para_filter = array();
    while (list ($key, $val) = each($para)) {
        if ($key == "token" || $val == "")
            continue;
        else
            $para_filter[$key] = $para[$key];
    }
    return $para_filter;
}

/**
 * 接口签名
 * @param array $param
 * @param string $first
 */
function api_sign($param, $origin = false) {
    $sign = concat($param) . global_config('secret_key');
    //return $sign;
    if ($origin)
        return $sign;
    return hash('md5', $sign);
}

/**
 * 获取全局配置
 * @param string $name 配置项名称
 * @param boolean $isReturn 如果出错，是否返回结果
 * @author 刘新
 */
function global_config($name, $isReturn = false) {
    $result = array('error' => 1, 'info' => false);
    //获取全局配置项
    $global = S(C('CONFIG_CACHE_NAME'));
    if (!$global) {
        $result['info'] = '配置项列表获取失败';
    } else {
        //配置项获取失败
        $config = $global[$name];
        if (!$config)
            $result['info'] = "配置项{$name}不存在";
    }

    //成功获取，则直接接返回
    if ($result['info'] === false)
        return $config['value'];

    //获取失败需判断
    if ($isReturn)
        return null;
    die(json_encode($result));
}

/** 错误日志
 * @param string $file 发生错误的文件
 * @param string|int $line 错误日志发生的等号
 * @param string|object $content
 * @author 刘新
 */
function record_error_log($file, $line, $content, $userId = null, $mobile = null, $type = 0) {
    if (is_object($content)) {
        $data['content'] = $content->getDbError() . '---' . $content->getError();
    } else {
        $data['content'] = $content;
    }
    $data['file'] = $file;
    $data['line'] = $line;
    $data['controller'] = CONTROLLER_NAME;
    $data['action'] = ACTION_NAME;
    $data['module'] = MODULE_NAME;
    $data['api_code'] = API_CODE;
    $data['type'] = $type;

    if ($userId)
        $data['user_id'] = $userId;
    if ($mobile)
        $data['mobile'] = $mobile;

    return D('ErrorLog')->addErrorLog($data);
}

/**
 * 内容过滤
 * @param $content
 * @author 刘新
 */
function validate_content($content, $option) {
    //最大长度校验
    if ($option['maxLength']) {
        if (mb_strlen($content) > $option['maxLength'])
            return false;

        //最小长度校验
    } else if ($option['minLength']) {
        if (mb_strlen($content) < $option['minLength'])
            return false;

        //如果有与正则表达式相匹配的项，则返回false
    } else if ($option['noRegex']) {
        if (preg_match($option['noRegex'], $content))
            return false;

        //如果不与正则表达式相匹配，返回false
    } else if ($option['yesRegex']) {
        if (!preg_match($option['yesRegex'], $content))
            return false;
    }

    return true;
}

/**
 * 发送全局信息
 */
function sendjpush($content) {

    include(dirname(dirname(dirname(__FILE__))) . '/Notify/jpush/src/JPush/JPush.php');

    $app_key = 'e7d0bb62c1622601523c2443';
    $master_secret = 'bcc98f903acd36a0ce054da9';

    // 初始化
    $client = new JPush($app_key, $master_secret);

    // 简单推送示例
    $result = $client->push()
            ->setPlatform('all')
            ->addAllAudience()
            ->setMessage($content)
            ->send();

    return $result;
}

/**
 * 针对单个用户发送
 */

/**
 * 发送全局信息
 */
function sendjpushbyuser($user_id, $content) {

    $userinfo = M("User")->where(array("id" => $user_id))->find();
    $registration_id = $userinfo['registration_id'];
    include(dirname(dirname(dirname(__FILE__))) . '/Notify/jpush/src/JPush/JPush.php');

    $app_key = 'e7d0bb62c1622601523c2443';
    $master_secret = 'bcc98f903acd36a0ce054da9';

    // 初始化
    $client = new JPush($app_key, $master_secret);

    // 简单推送示例
    $result = $client->push()
            ->setPlatform('all')
            ->addTags($registration_id)
            ->setMessage($content)
            ->send();

    return $result;
}

/**
 * 使用curl获取远程数据
 * @param  string $url url连接
 * @return string      获取到的数据
 */
function curl_get_contents($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);                //设置访问的url地址
    // curl_setopt($ch,CURLOPT_HEADER,1);               //是否显示头部信息
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);               //设置超时
    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);   //用户访问代理 User-Agent
    curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST']);        //设置 referer
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);          //跟踪301
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);        //返回结果
    $r = curl_exec($ch);
    curl_close($ch);
    return $r;
}

//打印输出数组信息
function printf_info($data) {
    foreach ($data as $key => $value) {
        echo "<font color='#00ff55;'>$key</font> : $value <br/>";
    }
}

/**
 * 退款
 * @param type $transaction_id  微信交易号
 * @param type $out_trade_no    商户订单号
 * @param type $total_fee       订单金额
 * @param type $refund_fee      退款金额
 * @return array 退款成功返回信息
 */
function wxRefund($transaction_id, $out_trade_no, $total_fee, $refund_fee) {
    vendor('WxPay.lib.WxPay', '', '.Api.php');
    if ($transaction_id != "") {
        $input = new \WxPayRefund();
        $input->SetTransaction_id($transaction_id);
        $input->SetTotal_fee($total_fee);
        $input->SetRefund_fee($refund_fee);
        $input->SetOut_refund_no(\WxPayConfig::MCHID . date("YmdHis"));
        $input->SetOp_user_id(\WxPayConfig::MCHID);
        return \WxPayApi::refund($input);
    }

    if ($out_trade_no != "") {
        $input = new \WxPayRefund();
        $input->SetOut_trade_no($out_trade_no);
        $input->SetTotal_fee($total_fee);
        $input->SetRefund_fee($refund_fee);
        $input->SetOut_refund_no(\WxPayConfig::MCHID . date("YmdHis"));
        $input->SetOp_user_id(\WxPayConfig::MCHID);
        return \WxPayApi::refund($input);
    }
}

/**
 * 快递公司
 */
function expressList() {
    $expressList = array(
        'ems' => 'EMS快递',
        'shentong' => '申通快递',
        'shunfeng' => '顺丰快递',
        'yuantong' => '圆通快递',
        'yunda' => '韵达快递',
        'huitong' => '百世汇通快递',
        'tiantian' => '天天快递',
        'zhongtong' => '中通快递',
        'pingyou' => '中国邮政',
        'quanfeng' => '全峰快递',
        'guotong' => '国通快递',
        'debang' => '德邦物流'
    );
    return $expressList;
}

/**
 * 支付宝当面付-条形码
 * @param type $outTradeNo (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线
 * @param type $subject (必填) 订单标题，粗略描述用户的支付目的。如“XX品牌XXX门店消费”
 * @param type $totalAmount (必填) 订单总金额，单位为元，不能超过1亿元
 * @param type $authCode    (必填) 付款条码，用户支付宝钱包手机app点击“付款”产生的付款条码
 * @param type $body (选填)订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
 */
function barPay($outTradeNo, $subject, $totalAmount, $authCode, $body) {
    vendor('Alipay.dangmianfu.f2fpay.model.builder.AlipayTradePayContentBuilder');
    vendor('Alipay.dangmianfu.f2fpay.service.AlipayTradeService');

    // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
    $providerId = ""; //系统商pid,作为系统商返佣数据提取的依据
    $extendParams = new ExtendParams();
    $extendParams->setSysServiceProviderId($providerId);
    $extendParamsArr = $extendParams->getExtendParams();
    // 支付超时，线下扫码交易定义为5分钟
    $timeExpress = "5m";

    // 商品明细列表，需填写购买商品详细信息，
    $goodsDetailList = array();

    // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
//    $goods1 = new \GoodsDetail();
//    $goods1->setGoodsId("good_id001");
//    $goods1->setGoodsName("XXX商品1");
//    $goods1->setPrice(3000);
//    $goods1->setQuantity(1);
//    //得到商品1明细数组
//    $goods1Arr = $goods1->getGoodsDetail();
//
//    // 继续创建并添加第一条商品信息，用户购买的产品为“xx牙刷”，单价为5.05元，购买了两件
//    $goods2 = new GoodsDetail();
//    $goods2->setGoodsId("good_id002");
//    $goods2->setGoodsName("XXX商品2");
//    $goods2->setPrice(1000);
//    $goods2->setQuantity(1);
//    //得到商品1明细数组
//    $goods2Arr = $goods2->getGoodsDetail();
//
//    $goodsDetailList = array($goods1Arr, $goods2Arr);
    //第三方应用授权令牌,商户授权系统商开发模式下使用
    $appAuthToken = ""; //根据真实值填写
    // 创建请求builder，设置请求参数
    $barPayRequestBuilder = new AlipayTradePayContentBuilder();
    $barPayRequestBuilder->setOutTradeNo($outTradeNo);
    $barPayRequestBuilder->setTotalAmount($totalAmount);
    $barPayRequestBuilder->setAuthCode($authCode);
    $barPayRequestBuilder->setTimeExpress($timeExpress);
    $barPayRequestBuilder->setSubject($subject);
    $barPayRequestBuilder->setBody($body);
    $barPayRequestBuilder->setUndiscountableAmount($undiscountableAmount);
    $barPayRequestBuilder->setExtendParams($extendParamsArr);
    $barPayRequestBuilder->setGoodsDetailList($goodsDetailList);
//    $barPayRequestBuilder->setStoreId($storeId);
//    $barPayRequestBuilder->setOperatorId($operatorId);
//    $barPayRequestBuilder->setAlipayStoreId($alipayStoreId);

    $barPayRequestBuilder->setAppAuthToken($appAuthToken);

    // 调用barPay方法获取当面付应答
    $barPay = new \AlipayTradeService(C('AliPayConf'));
    $barPayResult = $barPay->barPay($barPayRequestBuilder);

    switch ($barPayResult->getTradeStatus()) {
        case "SUCCESS":
            return ['status' => 'SUCCESS', 'info' => $barPayResult->getResponse()];
//            echo "支付宝支付成功:" . "<br>--------------------------<br>";
            break;
        case "FAILED":
//            echo "支付宝支付失败!!!" . "<br>--------------------------<br>";
            if (!empty($barPayResult->getResponse())) {
                return ['status' => 'FAILED', 'info' => $barPayResult->getResponse()];

//                print_r($barPayResult->getResponse());
            }
            break;
        case "UNKNOWN":
//            echo "系统异常，订单状态未知!!!" . "<br>--------------------------<br>";
            if (!empty($barPayResult->getResponse())) {
                return ['status' => 'UNKNOWN', 'info' => $barPayResult->getResponse()];
//                print_r($barPayResult->getResponse());
            }
            break;
        default:
            return ['status' => 'UNKNOWN', 'info' => '不支持的交易状态，交易返回异常!!!'];

//            echo "不支持的交易状态，交易返回异常!!!";
            break;
    }
    return;
}

/**
 * 装箱型号列表
 * small_carpool-小柜拼车 small_single-小柜单放 big_cabinet-大柜 tall_cabinet-高柜 super_tall_cabinet-超高柜
 */
function boxModel() {
    $boxModelList = array(
        'small_carpool',
        'small_single',
        'big_cabinet',
        'tall_cabinet',
        'super_tall_cabinet',
    );
    return $boxModelList;
}

function boxModelList($box_model) {
    $boxModelList = array(
        'small_carpool' => '小柜拼车（1x20GP）',
        'small_single' => '小柜单放（1x20GP）',
        'big_cabinet' => '大柜（1x40GP）',
        'tall_cabinet' => '高柜（1x40HQ）',
        'super_tall_cabinet' => '超高柜（1x45HQ）',
    );
    return empty($box_model) ? $boxModelList : $boxModelList[$box_model];
}

/**
 * 消息模块
 * @param type $app_type
 * @param type $message_type
 */
function messageModel($app_type = 0, $message_type, $data = []) {
    if (empty($data)) {
        return '';
    }
    switch ($app_type) {
        case '1':
            //司机端
            $msg_list = array(
                '1' => '您有一个新的装箱订单，请及时完成(提单号：SH999778，箱封号：F879389，司机手机号：13490873082)'
            );
            break;
        case '2':
            //装箱工
            $msg_list = array(
                '1' => '您有一个新的指派订单，请及时完成(提单号：SH999778，箱封号：F879389，司机手机号：13490873082)',
            );
            break;
        case '3':
            //企业端
            $msg_list = array(
                '1' => '司机已接单，将在约定时间出发去港口提箱(提单号：$box，箱封号：F879389，司机手机号：13490873082)',
                '2' => '司机已完成提箱，正在前往装箱点装货(提单号：SH999778，箱封号：F879389，司机手机号：13490873082)',
                '3' => '司机已接到所有货物进港，等待清关装船。请及时确认货物是否到港(提单号：SH999778，箱封号：F879389，司机手机号：13490873082)',
            );
            break;
    }
}

/**
 * 物流消息写入
 * @param type $app_type
 */
function logisticsInsert($order_id, $message_type) {
    $arrLogistics = array(
        '1' => '司机已接单，将在约定时间出发去港口提箱',
        '1' => '司机已到港口提箱成功，正在前往装箱地点',
        '1' => '司机已装货进港，请核对货物是否到港',
    );
    $data['order_id'] = $order_id;
    $data['logistics_title'] = $arrLogistics[$message_type];
    $order_logistics_id = M('order_logistics')->add($data);
    return $order_logistics_id;
}

function uploadFileBase64($base64Data, $dir = 'Picture') {
    $code = md5(time() + mt_rand(1, 9999));
    $savePath = '/Uploads/' . $dir . '/' . $code . '.png';
    $s = file_put_contents('.' . $savePath, base64_decode($base64Data)); //返回的是字节数
    return $savePath;
}

/**
 * 封装base64位图片上传
 */
function base64_upload($base64, $dir = 'Picture') {
    $base64_image = str_replace(' ', '+', $base64);
    //post的数据里面，加号会被替换为空格，需要重新替换回来，如果不是post的数据，则注释掉这一行
    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image, $result)) {
        //匹配成功
        if ($result[2] == 'jpeg') {
            $image_name = uniqid() . '.jpg';
            //纯粹是看jpeg不爽才替换的
        } else {
            $image_name = uniqid() . '.' . $result[2];
        }
        $image_file = "/Uploads/" . $dir . "/{$image_name}";
        //服务器文件存储路径
        if (file_put_contents('.' . $image_file, base64_decode(str_replace($result[1], '', $base64_image)))) {
            return $image_file;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

function juheSms($phone, $code) {
    $sendUrl = 'http://v.juhe.cn/sms/send'; //短信接口的URL
    $smsConf = array(
        'key' => 'b3ef0ded6691c0e8f3348715592211a2', //您申请的APPKEY
        'mobile' => $phone, //接受短信的用户手机号码
        'tpl_id' => '70604', //您申请的短信模板ID，根据实际情况修改
        'tpl_value' => "#code#={$code}" //您设置的模板变量，根据实际情况修改
    );
    $content = juhecurl($sendUrl, $smsConf, 1); //请求发送短信

    if ($content) {
        $result = json_decode($content, true);
        $error_code = $result['error_code'];
        if ($error_code == 0) {
            //状态为0，说明短信发送成功
//            echo "短信发送成功,短信ID：" . $result['result']['sid'];
            return TRUE;
        } else {
            //状态非0，说明失败
            $msg = $result['reason'];
//            echo "短信发送失败(" . $error_code . ")：" . $msg;
            return FALSE;
        }
    } else {
        //返回内容异常，以下可根据业务逻辑自行修改
//        echo "请求发送短信失败";
        return FALSE;
    }
}

/**
 * 请求接口返回内容
 * @param  string $url [请求的URL地址]
 * @param  string $params [请求的参数]
 * @param  int $ipost [是否采用POST形式]
 * @return  string
 */
function juhecurl($url, $params = false, $ispost = 0) {
    $httpInfo = array();
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22');
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    if ($ispost) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        curl_setopt($ch, CURLOPT_URL, $url);
    } else {
        if ($params) {
            curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
        } else {
            curl_setopt($ch, CURLOPT_URL, $url);
        }
    }
    $response = curl_exec($ch);
    if ($response === FALSE) {
        //echo "cURL Error: " . curl_error($ch);
        return false;
    }
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
    curl_close($ch);
    return $response;
}

function ExcelOrder($Obj, $uid) {

    /* 引入phpexcel核心类文件 */

    import("Vendor.PHPExcel");

    /* 实例化excel类 */

    $excel = new \PHPExcel();


    /* 设置文本对齐方式 */

    $excel->getDefaultStyle()->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);

    $excel->getDefaultStyle()->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);

    $objActSheet = $excel->getActiveSheet();

    $letter = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N');

    /* 设置表头数据 */
    $tableheader = array('订单号', '下单企业', '提单号', '订单状态', '箱型', '装箱时间', '截关时间', '装箱点', '货重', '运费', '下单时间');


    /*    填充表格表头 */

    for ($i = 0; $i < count($tableheader); $i++) {

        $excel->getActiveSheet()->setCellValue("$letter[$i]1", "$tableheader[$i]");
        /* 设置font */
        $excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->setName(iconv('gbk', 'utf-8', '宋体'));
        $excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->setSize(16);
        $excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->setBold(true);
        /* 设置下划线 */
        //$excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
        /* 设置字体颜色 */
        //$excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->getColor()->setARGB(PHPExcel_Style_Color::COLOR_WHITE);
        //$excel->getActiveSheet()->getStyle("$letter[$i]1")->getFont()->getColor()->setARGB(PHPExcel_Style_Color::COLOR_WHITE);
        /* 设置表格宽度 */
//        $objActSheet->getColumnDimension("$letter[$i]")->setWidth(20);
//        $objActSheet->getColumnDimension("$letter[2]")->setWidth(30);
//        $objActSheet->getColumnDimension("$letter[5]")->setWidth(10);
    }

    $startdate = !empty($_POST['startdate']) ? $_POST['startdate'] : date('Y-m-d', time());

    $box['small_carpool'] = '小柜拼车';
    $box['small_single'] = '小柜单放';
    $box['big_cabinet'] = '大柜';
    $box['tall_cabinet'] = '高柜';
    $box['super_tall_cabinet'] = '超高柜';

    $status_map[0] = '待支付';
    $status_map[10] = '派单中';
    $status_map[20] = '待企业确认';
    $status_map[30] = '进行中';
    $status_map[40] = '已到港';
    $status_map[50] = '已完成';
    $status_map[60] = '已取消';


    /* 设置表格数据 */

    if (!empty($Obj)) {
        foreach ($Obj as $k => $v) {
//    
            if ($uid >= 1) {
                $Obj[$k]['company_name'] = '集运邦';
            }
            $Obj[$k]['order_type'] = $box[$v['order_type']];
            $Obj[$k]['order_type'] = $box[$v['order_type']];

            if ($v['order_status'] == 10 && $v['fleet_id'] == 0) {
                $Obj[$k]['order_status'] = '待分配车队';
            } elseif ($v['order_status'] == 10 && $v['driver_id'] == 0) {
                $Obj[$k]['order_status'] = '待分配司机';
            } else {
                $Obj[$k]['order_status'] = $status_map[$v['order_status']];
            }

            $Obj[$k]['address'] = $v['province'] . $v['city'] . $v['address'] . $v['address_desc'];
        }
    }


    /* 向每行单元格插入数据 */

    for ($i = 0; $i < count($Obj); $i++) {



        $j = $i + 2;

        /* 设置表格高度 */

//        $excel->getActiveSheet()->getRowDimension($j)->setRowHeight(35);
//        $excel->getActiveSheet()->getStyle($j)->getFont()->setSize(12);
        /* 设置表格格式 */
        $excel->getActiveSheet()->getStyle("$letter[2]$j")->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_NUMBER);
        for ($row = 0; $row < count($Obj[$i]); $row++) {
            if ($row == (count($Obj[$i]) - 1 )) {

//                $tableheader = array('订单号', '下单企业', '提单号', '订单状态', '箱型', '装箱时间', '截关时间', '装箱点', '货重', '运费', '下单时间');

                $excel->getActiveSheet()->setCellValue("$letter[0]$j", $Obj[$i]['order_no'] . ' ');
                $excel->getActiveSheet()->setCellValue("$letter[1]$j", $Obj[$i]['company_name']);
                $excel->getActiveSheet()->setCellValue("$letter[2]$j", $Obj[$i]['pick_no'] . ' ');
                $excel->getActiveSheet()->setCellValue("$letter[3]$j", $Obj[$i]['order_status']);
                $excel->getActiveSheet()->setCellValue("$letter[4]$j", $Obj[$i]['order_type']);
                $excel->getActiveSheet()->setCellValue("$letter[5]$j", $Obj[$i]['shipment_time']);
                $excel->getActiveSheet()->setCellValue("$letter[6]$j", $Obj[$i]['cutoff_time']);
                $excel->getActiveSheet()->setCellValue("$letter[7]$j", $Obj[$i]['address']);
                $excel->getActiveSheet()->setCellValue("$letter[8]$j", $Obj[$i]['weight_desc']);
                $excel->getActiveSheet()->setCellValue("$letter[9]$j", $Obj[$i]['order_price']);
                $excel->getActiveSheet()->setCellValue("$letter[10]$j", $Obj[$i]['create_time']);
            }
        }
    }
    $date = "订单导出-" . $startdate;

    /* 实例化excel输入类并完成输出excel文件 */

    $write = new \PHPExcel_Writer_Excel5($excel);
    //var_dump($write);exit;

    header("Pragma: public");

    header("Expires: 0");

    header("Cache-Control:must-revalidate, post-check=0, pre-check=0");

    header("Content-Type:application/force-download");

    header("Content-Type:application/vnd.ms-execl");

    header("Content-Type:application/octet-stream");

    header("Content-Type:application/download");
    header("Content-Disposition:attachment;filename=$date.xls");

    header("Content-Transfer-Encoding:binary");

    $write->save('php://output');


    exit;


    //var_dump($row);exit;
}
